<!DOCTYPE html>
<html lang="zh-cn">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>贪吃蛇</title>
</head>
<body onload="draw()" style="text-align: center;padding: 0;margin: 0;">
<canvas id="canvas" width="800" height="600" style="border: 1px solid #000;"></canvas>
  <script>
    function draw(){
      let canvas = document.querySelector("#canvas");
      if(canvas.getContext){
        let cvsCtx = canvas.getContext("2d");
        //贪吃蛇步骤
        //1.画蛇(蛇头 蛇身-数组)
        //2.让蛇运动
        //3.随机投放食物
        //4.吃食物
        //5.边缘检测，判断游戏结束
        let timer = null;
        function Rect(x,y,width,height,color){
          this.x = x;
          this.y = y;
          this.width = width;
          this.height = height;
          this.color = color;
        }
        Rect.prototype.rDraw = function(){
          cvsCtx.beginPath();
          cvsCtx.fillStyle = this.color;
          cvsCtx.fillRect(this.x, this.y, this.width, this.height);
          cvsCtx.strokeRect(this.x, this.y, this.width, this.height);
          cvsCtx.closePath();
        }
        function Snake(){
          //蛇头this.head
          this.head = new Rect(canvas.width/2-50,canvas.height/2-20,40,40,"#000");
          //蛇身Array
          this.body = [];
          let x = this.head.x - 40;
          let y = this.head.y;
          for(let i=0; i<3;i++){
            let rect = new Rect(x,y,40,40,"#eee");
            this.body.push(rect);
            x -= 40;
          }
          this.isEat = false;
          this.direction = 2;
        }
        Snake.prototype.sDraw = function(){
          this.head.rDraw();
          for(let i=0; i<this.body.length; i++){
            this.body[i].rDraw();
          }
        }
        Snake.prototype.move = function(){
          //加头去尾
          let rect = new Rect(this.head.x,this.head.y,40,40,"#eee");
          this.body.splice(0,0,rect);
          if(!this.isEat){
            this.body.pop()
          }else{
            this.isEat = false;
          }
          switch(this.direction){
            case 0:
              this.head.x -= this.head.width;
              break;
            case 1:
              this.head.y -= this.head.height;
              break;
            case 2:
              this.head.x += this.head.width;
              break;
            case 3:
              this.head.y += this.head.height;
              break;
          }
          //判断撞墙
          if(this.head.x>canvas.width-this.head.width||this.head.x<0||this.head.y>canvas.height-this.head.height||this.head.y<0){
            clearInterval(timer);
            timer = null;
            alert("游戏结束");
            
          }
          //判断蛇头蛇身碰撞
          for(let i=0; i<this.body.length; i++){
              if(isRectHit(this.head,this.body[i])){
                clearInterval(timer);
                timer = null;
                alert("游戏结束");  
              }
            }
      
        }
        
        function getRandom(min,max){
          //round四舍五入，随机取左也取右
          return Math.round(Math.random()*(max-min))+min;
        }
        function isRectHit(rect1,rect2){
          let minx1 = rect1.x;
          let miny1 = rect1.y;
          let minx2 = rect2.x;
          let miny2 = rect2.y;
          let maxx1 = rect1.x + rect1.width;
          let maxy1 = rect1.y + rect1.height;
          let maxx2 = rect2.x + rect2.width;
          let maxy2 = rect2.y + rect2.height;

          let minx = Math.max(minx1,minx2);
          let maxx = Math.min(maxx1,maxx2);
          let miny = Math.max(miny1,miny2);
          let maxy = Math.min(maxy1,maxy2);

          if(minx<maxx && miny<maxy){
            return true;
          }
          return false;
        }
        function ranForFood(){
          //是否与蛇重合
          let isInSnake = true;
          while(isInSnake){
            let x = getRandom(0,canvas.width-40);
            let y = getRandom(0,canvas.height-40);
            var rect = new Rect(x,y,40,40,"pink");

            //食物是否与蛇头重合
            if(isRectHit(snake.head,rect)){
              isInSnake = true;
              continue;
            }
            isInSnake = false;
            //食物是否与蛇身重合
            for(let i=0; i<snake.body.length; i++){
              if(isRectHit(snake.body[i],rect)){
                isInSnake = true;
                break;
              }
            }
          }
          return rect;
        }
        function animate(){
          cvsCtx.clearRect(0, 0, canvas.width, canvas.height);
          food.rDraw();
          snake.move();
          snake.sDraw();
          if(isRectHit(snake.head,food)){
            snake.isEat = true;
            food = ranForFood();
          }
          
        }
        let snake = new Snake();
        let food = ranForFood();
        food.rDraw();
        timer = setInterval(animate,50);
        document.onkeydown = function(event){
          let ev = event || window.event;
          let direction = snake.direction;
          switch(ev.keyCode){
            case 65:
            case 37: 
              snake.direction = direction!==2?0:direction;
              break;
            case 87:
            case 38: 
              snake.direction = direction!==3?1:direction;
              break;
            case 68:
            case 39: 
              snake.direction = direction!==0?2:direction;
              break;
            case 83:
            case 40: 
              snake.direction = direction!==1?3:direction;
              break;
          }
        }
      }
    }
  </script>
</body>
</html>